import { CalcData } from "@/core/calc"
import { useCharacterStore } from "@/store"
import { StatusOptions } from "./status"

type SkillEffect = (context: SkillContext, data: CalcData) => Partial<SkillResult> | void
//技能帧
export interface SkillFrame {
    attack: number
    hits: number
}

export interface Skill {
    effect: SkillEffect
    /**
     * 等级间隔
     */
    readonly level_spacing: number

    /**
     * 精通等级
     */
    readonly level_master: number

    /**
     * 等级上限
     */
    readonly level_max: number

    /**
     * 学习技能所需的角色等级
     */
    readonly need_level: number

    readonly name: string

    readonly type: SkillType

    // 冷却时间(s)
    readonly cooldown?: number

    // 技能点
    readonly point?: number
}

export enum SkillType {
    PASSIVE = 1, //被动技能
    BUFF = 2, //buff技能
    ACTIVE = 4, //主动技能
    AWAKE = 8 //觉醒技能
}

export interface SkillContext {
    adapt_number: number
    skill_name: string
    level: number
    cdr: number
    attack: number
    add_level: number
    useSkill: (name: string) => (() => Partial<SkillResult>) | undefined
}
export interface SkillColumn {
    skill: Skill
    add_level: number
    enabled: boolean
}

export interface SkillResult {
    name: string
    level: number
    value: StatusOptions
    frames: SkillFrame[]
    adapt_number: number
    damage: number
}

export const CDR = "cd_raduction"
export const ATTACK_ADD = "attack_add"
export const LEVEL_ADD = "level_add"
const NONE = "none"
type SkillEntryType = "cd_raduction" | "attack_add" | "level_add" | "none"

export interface SkillCondition {
    levels: number[]
    names: string[]
    ignores: number[]
    type: SkillType
    jobs: string[] | false
}

interface SkillEntryBase {
    /**
     * 起始等级
     */
    start: number
    /**
     * 结束等级
     */
    end: number

    type: SkillEntryType

    /**
     * 冷却缩减
     */
    value: number
}

export interface SkillEntry extends SkillEntryBase {
    condition: SkillCondition
}

export interface SkillEntryOptions extends Partial<SkillEntryBase> {
    condition?: Partial<SkillCondition>
}

export function createSkillEntry(options: SkillEntryOptions = {}): SkillEntry {
    return {
        start: options.start ?? 0,
        end: options.end ?? 0,
        value: options.value ?? 0,
        type: options.type ?? LEVEL_ADD,
        condition: {
            levels: options.condition?.levels ?? [],
            names: options.condition?.names ?? [],
            ignores: options.condition?.ignores ?? [],
            type: options.condition?.type ?? SkillType.PASSIVE,
            jobs: options.condition?.jobs ?? []
        }
    }
}

export function createSkillContext(context: SkillContext, data: CalcData) {
    const { skill_entries } = data

    const { character_level } = useCharacterStore()

    return function (column: SkillColumn): SkillContext {
        const { skill } = column
        const { need_level, name, level_master, level_max, level_spacing } = skill
        let add_level = 0
        let attack = 0
        let cdr = 1
        for (let entry of skill_entries) {
            let { start, end, condition, type, value } = entry
            const { ignores = [], names = [], levels = [], type: condition_type = SkillType.PASSIVE } = condition
            if (ignores.includes(need_level)) {
                continue
            }
            if (condition_type > skill.type) {
                continue
            }

            if ((need_level >= start && (need_level <= end || end < 0)) || names.includes(name) || levels.includes(need_level)) {
                switch (type) {
                    case LEVEL_ADD:
                        add_level = add_level.plus(value)
                        break
                    case ATTACK_ADD:
                        attack = attack.perMulti(value)
                        break
                    case CDR:
                        cdr = cdr.multiply((1.0).minus(value))
                        break
                }
            }
        }

        let level = character_level.plus(5).minus(need_level).exactlyDivide(level_spacing).plus(1)

        level = Math.max(level, 0)
        level = Math.min(level, level_master)

        level = Math.min(level.plus(add_level), level_max)
        return {
            ...context,
            attack,
            cdr,
            add_level,
            level,
            skill_name: skill.name
        }
    }
}

export function createSkillColumn(skill: Skill): SkillColumn {
    return {
        skill,
        add_level: 0,
        enabled: true
    }
}
